50ea21c2a13e20eac0908f4262828b3ab8eff21f,src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java,StaticTypeCheckingVisitor,inferReturnTypeGenerics,#ClassNode#MethodNode#Expression#,1853
Before Change
}
}
if (!returnType.isUsingGenerics()) return returnType;
GenericsType[] returnTypeGenerics = returnType.getGenericsTypes();
List<GenericsType> placeholders = new LinkedList<GenericsType>();
for (GenericsType returnTypeGeneric : returnTypeGenerics) {
if (returnTypeGeneric.isPlaceholder() || returnTypeGeneric.isWildcard()) {
placeholders.add(returnTypeGeneric);
}
}
if (placeholders.isEmpty()) return returnType; // nothing to infer
Map<String,GenericsType> resolvedPlaceholders = new HashMap<String, GenericsType>();
GenericsUtils.extractPlaceholders(receiver, resolvedPlaceholders);
GenericsUtils.extractPlaceholders(method.getReturnType(), resolvedPlaceholders);
// then resolve receivers from method arguments
Parameter[] parameters = method.getParameters();
boolean isVargs = isVargs(parameters);
ArgumentListExpression argList = InvocationWriter.makeArgumentList(arguments);
List<Expression> expressions = argList.getExpressions();
int paramLength = parameters.length;
for (int i = 0; i < paramLength; i++) {
boolean lastArg = i== paramLength -1;
ClassNode type = parameters[i].getType();
if (!type.isUsingGenerics() && type.isArray()) type=type.getComponentType();
if (type.isUsingGenerics()) {
ClassNode actualType = getType(expressions.get(i));
if (isVargs && lastArg && actualType.isArray()) {
actualType=actualType.getComponentType();
}
actualType = wrapTypeIfNecessary(actualType);
Map<String, GenericsType> typePlaceholders = GenericsUtils.extractPlaceholders(type.isArray()?type.getComponentType():type);
if (OBJECT_TYPE.equals(type)) {
// special case for handing Object<E> -> Object
for (String key : typePlaceholders.keySet()) {
resolvedPlaceholders.put(key, new GenericsType(actualType));
}
} else {
while (!actualType.equals(type)) {
Set<ClassNode> interfaces = actualType.getAllInterfaces();
boolean intf = false;
for (ClassNode anInterface : interfaces) {
if (anInterface.equals(type)) {
intf = true;
actualType = GenericsUtils.parameterizeInterfaceGenerics(actualType, anInterface);
}
}
if (!intf) actualType = actualType.getUnresolvedSuperClass();
}
Map<String, GenericsType> actualTypePlaceholders = GenericsUtils.extractPlaceholders(actualType);
for (Map.Entry<String, GenericsType> typeEntry : actualTypePlaceholders.entrySet()) {
String key = typeEntry.getKey();
GenericsType value = typeEntry.getValue();
GenericsType alias = typePlaceholders.get(key);
if (alias != null && alias.isPlaceholder()) {
resolvedPlaceholders.put(alias.getName(), value);
}
}
}
}
}
GenericsType[] copy = new GenericsType[returnTypeGenerics.length];
for (int i = 0; i < copy.length; i++) {
GenericsType returnTypeGeneric = returnTypeGenerics[i];
if (returnTypeGeneric.isPlaceholder() || returnTypeGeneric.isWildcard()) {
GenericsType resolved = resolvedPlaceholders.get(returnTypeGeneric.getName());
if (resolved==null) resolved = returnTypeGeneric;
copy[i] = resolved;
} else {
copy[i] = returnTypeGeneric;
}
}
if (returnType.equals(OBJECT_TYPE)) {
return copy[0].getType();
}
returnType = returnType.getPlainNodeReference();
returnType.setGenericsTypes(copy);
if (returnType.equals(Annotation_TYPE) && returnType.getGenericsTypes()!=null && !returnType.getGenericsTypes()[0].isPlaceholder()) {
return returnType.getGenericsTypes()[0].getType();
}
After Change
}
}
if (!isUsingGenericsOrIsArrayUsingGenerics(returnType)) return returnType;
GenericsType[] returnTypeGenerics = returnType.isArray()?returnType.getComponentType().getGenericsTypes():returnType.getGenericsTypes();
List<GenericsType> placeholders = new LinkedList<GenericsType>();
for (GenericsType returnTypeGeneric : returnTypeGenerics) {
if (returnTypeGeneric.isPlaceholder() || returnTypeGeneric.isWildcard()) {
placeholders.add(returnTypeGeneric);
}
}
if (placeholders.isEmpty()) return returnType; // nothing to infer
Map<String,GenericsType> resolvedPlaceholders = new HashMap<String, GenericsType>();
GenericsUtils.extractPlaceholders(receiver, resolvedPlaceholders);
GenericsUtils.extractPlaceholders(method.getReturnType(), resolvedPlaceholders);
// then resolve receivers from method arguments
Parameter[] parameters = method.getParameters();
boolean isVargs = isVargs(parameters);
ArgumentListExpression argList = InvocationWriter.makeArgumentList(arguments);
List<Expression> expressions = argList.getExpressions();
int paramLength = parameters.length;
if (expressions.size()>=paramLength) {
for (int i = 0; i < paramLength; i++) {
boolean lastArg = i == paramLength - 1;
ClassNode type = parameters[i].getType();
if (!type.isUsingGenerics() && type.isArray()) type = type.getComponentType();
if (type.isUsingGenerics()) {
ClassNode actualType = getType(expressions.get(i));
if (isVargs && lastArg && actualType.isArray()) {
actualType = actualType.getComponentType();
}
actualType = wrapTypeIfNecessary(actualType);
Map<String, GenericsType> typePlaceholders = GenericsUtils.extractPlaceholders(type.isArray() ? type.getComponentType() : type);
if (OBJECT_TYPE.equals(type)) {
// special case for handing Object<E> -> Object
for (String key : typePlaceholders.keySet()) {
resolvedPlaceholders.put(key, new GenericsType(actualType));
}
} else {
while (!actualType.equals(type)) {
Set<ClassNode> interfaces = actualType.getAllInterfaces();
boolean intf = false;
for (ClassNode anInterface : interfaces) {
if (anInterface.equals(type)) {
intf = true;
actualType = GenericsUtils.parameterizeInterfaceGenerics(actualType, anInterface);
}
}
if (!intf) actualType = actualType.getUnresolvedSuperClass();
}
Map<String, GenericsType> actualTypePlaceholders = GenericsUtils.extractPlaceholders(actualType);
for (Map.Entry<String, GenericsType> typeEntry : actualTypePlaceholders.entrySet()) {
String key = typeEntry.getKey();
GenericsType value = typeEntry.getValue();
GenericsType alias = typePlaceholders.get(key);
if (alias != null && alias.isPlaceholder()) {
resolvedPlaceholders.put(alias.getName(), value);
}
}
}
}
}
}
GenericsType[] copy = new GenericsType[returnTypeGenerics.length];
for (int i = 0; i < copy.length; i++) {
GenericsType returnTypeGeneric = returnTypeGenerics[i];
if (returnTypeGeneric.isPlaceholder() || returnTypeGeneric.isWildcard()) {
GenericsType resolved = resolvedPlaceholders.get(returnTypeGeneric.getName());
if (resolved==null) resolved = returnTypeGeneric;
copy[i] = resolved;
} else {
copy[i] = returnTypeGeneric;
}
}
if (returnType.equals(OBJECT_TYPE)) {
return copy[0].getType();
}
if (returnType.isArray()) {
returnType = returnType.getComponentType().getPlainNodeReference();
returnType.setGenericsTypes(copy);
if (OBJECT_TYPE.equals(returnType)) {
// replace Object<Component> with Component
returnType = copy[0].getType();
}
returnType = returnType.makeArray();
} else {
returnType = returnType.getPlainNodeReference();
returnType.setGenericsTypes(copy);
}
if (returnType.equals(Annotation_TYPE) && returnType.getGenericsTypes()!=null && !returnType.getGenericsTypes()[0].isPlaceholder()) {
return returnType.getGenericsTypes()[0].getType();